6364ef2fe0ad6ca68c4b529d4a6eae1f3848c59c,src/main/java/org/datanucleus/metadata/ClassMetaData.java,ClassMetaData,addMetaDataForMembersNotInMetaData,#Class#,350

Before Change


                                    {
                                        // User has class declaration like "public class MyClass<T extends SomeType>" so take SomeType
                                        boolean overrideIfNotPresent = true;
                                        AbstractMemberMetaData overriddenMmd = getMetaDataForMember(ClassUtils.getFieldNameForJavaBeanGetter(allclsMethods[i].getName()));
                                        if (overriddenMmd != null)
                                        {
                                            if (!overriddenMmd.getTypeName().equals(((Class)boundTypes[0]).getName()))
                                            {
                                                // Already overridden the type in a superclass, so ignore
                                                overrideIfNotPresent = false;
                                            }
                                        }

                                        // TODO Maybe should use just the declTypes for this specific class?
                                        if (overrideIfNotPresent)
                                        {
                                            NucleusLogger.METADATA.debug("Class=" + cls.getName() + " property=" + allclsMethods[i].getName() +
                                                " declared to be " + methodTypeVar + ", namely TypeVariable(" + j + ") with bound, so using bound of " + boundTypes[0]);
                                            String propertyName = allclsMethods[i].getDeclaringClass().getName() + "." + ClassUtils.getFieldNameForJavaBeanGetter(allclsMethods[i].getName());
                                            if (!memberNames.contains(propertyName))
                                            {
                                                // No property of this name - add a default PropertyMetaData for this method with the type set to what we need
                                                NucleusLogger.METADATA.debug(Localiser.msg("044060", fullName, propertyName));

                                                // TODO Use MetaDataMerger to merge with the overridden
                                                AbstractMemberMetaData mmd = new PropertyMetaData(this, propertyName);
                                                mmd.type = (Class) boundTypes[0];
                                                members.add(mmd);

                                                memberNames.add(mmd.getName());
                                                Collections.sort(members);
                                                foundTypeForTypeVariable = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                // Check for any TypeVariables used with fields in superclass(es) and override the metadata in the superclass to use the right type
                Class theClass = cls;
                while (theClass.getSuperclass() != null)
                {
                    theClass = theClass.getSuperclass();
                    Field[] theclsFields = theClass.getDeclaredFields();
                    for (int i=0;i<theclsFields.length;i++)
                    {
                        if (!ClassUtils.isInnerClass(theclsFields[i].getName()) && !Modifier.isStatic(theclsFields[i].getModifiers()) &&
                            !mmgr.isEnhancerField(theclsFields[i].getName()) &&
                            theclsFields[i].getGenericType() != null && theclsFields[i].getGenericType() instanceof TypeVariable)
                        {
                            TypeVariable fieldTypeVar = (TypeVariable) theclsFields[i].getGenericType();
                            Class declCls = theclsFields[i].getDeclaringClass();
                            TypeVariable[] declTypes = declCls.getTypeParameters();
                            if (declTypes != null)
                            {
                                for (int j=0;j<declTypes.length;j++)
                                {
                                    boolean foundTypeForTypeVariable = false;
                                    if (declTypes[j].getName().equals(fieldTypeVar.getName()) && cls.getGenericSuperclass() instanceof ParameterizedType)
                                    {
                                        ParameterizedType genSuperclsType = (ParameterizedType) cls.getGenericSuperclass();
                                        Type[] paramTypeArgs = genSuperclsType.getActualTypeArguments();
                                        if (paramTypeArgs != null && paramTypeArgs.length > j && paramTypeArgs[j] instanceof Class)
                                        {
                                            NucleusLogger.METADATA.debug("Class=" + cls.getName() + " field=" + theclsFields[i].getName() +
                                                " declared to be " + fieldTypeVar + ", namely TypeVariable(" + j + ") of " + declCls.getName() + " so using " + paramTypeArgs[j]);
                                            String memberName = declCls.getName() + "." + theclsFields[i].getName();
                                            if (!memberNames.contains(memberName))
                                            {
                                                if (hasProperties && api.equalsIgnoreCase("JPA"))
                                                {
                                                    // Do nothing, since we will have a property
                                                }
                                                else
                                                {
                                                    // No member of this name - add a default FieldMetaData for this field with the type set to what we need
                                                    NucleusLogger.METADATA.debug(Localiser.msg("044060", fullName, memberName));
                                                    AbstractMemberMetaData overriddenMmd = getMemberBeingOverridden(theclsFields[i].getName());

                                                    // Merge the overridden member with the limited info specified in this override
                                                    AbstractMemberMetaData mmd = new FieldMetaData(this, memberName);
                                                    // Note that if we override a single PK field we will have objectIdClass=ObjectId in the generics superclass, and still ObjectId here
                                                    // We have to keep to continue like this since the superclass will have been enhanced to have ObjectId in its bytecode contract.
                                                    mergeMemberMetaDataForOverrideOfType((Class) paramTypeArgs[j], mmd, overriddenMmd);

                                                    members.add(mmd);
                                                    memberNames.add(mmd.getName());
                                                    Collections.sort(members);
                                                }
                                                foundTypeForTypeVariable = true;
                                            }
                                            else
                                            {
                                                // TODO Cater for the user overriding it
                                            }
                                        }
                                    }
                                    if (!foundTypeForTypeVariable)
                                    {
                                        // Try bounds of declType
                                        Type[] boundTypes = declTypes[j].getBounds();
                                        // TODO Maybe should use just the declTypes for this specific class?
                                        if (boundTypes != null && boundTypes.length == 1 && boundTypes[0] instanceof Class)
                                        {
                                            // User has class declaration like "public class MyClass<T extends SomeType>" so take SomeType
                                            // TODO What if a superclass has already resolved the type? Do like with properties above?
                                            NucleusLogger.METADATA.debug("Class=" + cls.getName() + " field=" + theclsFields[i].getName() +
                                                " declared to be " + fieldTypeVar + ", namely TypeVariable(" + j + ") with bound, so using bound of " + boundTypes[0]);
                                            String fieldName = declCls.getName() + "." + theclsFields[i].getName();
                                            if (!memberNames.contains(fieldName))

After Change


                                            if (!memberNames.contains(fieldName))
                                            {
                                                // Field defined as generic but not found a meta-data definition, so use boundTypes to add override meta-data with the correct type
                                                NucleusLogger.METADATA.debug(Localiser.msg("044060", fullName, fieldNameFull));

                                                // TODO Use MetaDataMerger to merge with superclass
                                                AbstractMemberMetaData mmd = new FieldMetaData(this, fieldNameFull);